home *** CD-ROM | disk | FTP | other *** search
- * pages.src
- * pages procedures file
- * Andrew Schulman, 12 Humboldt St., Cambridge MA 02140
- * 11/16/86
- * revised 11/18/86: replaced pack with list while .not. deleted()
- * revised 11/19/86: added check for .not. deleted() before clearing screen
- * revised 11/21/86: no recursion: pages & caller share variable thisfile
- * revised 11/21/86: any len(line) ok: list off trim(substr(line,1,length))
- * but added test for field name line
- * revised 11/24/86: added parameter SWITCH_OK: let calling program
- * determine if OK to go to another file
-
- procedure PAGES
- parameters FILENAME, MYTOP, DEPTH, START, SHOWPAGE, SHOWRULE, SWITCH_OK
-
- **************************** error checking *************************
- if DEPTH + START > 22 .or. START > 22 .or. SHOWPAGE > START .or. ;
- SHOWRULE > START
- @3,0 say "PAGES won't fit on screen or SHOWPAGE/SHOWRULE won't show"
- @4,0 say "Correct example: do PAGES with 'pages.src', 1, 19, 3, 1, 2"
- return
- endif
- if .not. file(FILENAME)
- @START,0 say "PAGES can't find " + FILENAME
- return
- endif
-
- ****************************** definitions ************************
- * below are scan codes for PC keys: note that these shouldn't be variables,
- * which is what they are here, but shouldn't be dropped in code as "magic
- * numbers" either. dBase needs something like #define in C. There IS a
- * keyword "define" in DB++ preprocessor I'm writing. Also user-defined
- * functions and procedures INSIDE same file as non-procedures. Readers are
- * invited to send me their "wish lists." Right now I'm writing the pre-
- * processor in dBase so that dBase programmers can modify it. Parsing in
- * dBase relies heavily on functions substr() and at() and works fine but is
- * slow! Might just write it in C. Anyway...
- up = 5
- down = 24
- pgUp = 18
- pgDn = 3
- homekey = 1
- endkey = 6
-
- ****************************** set up ******************************
- store space(10) to whichpage, phrase, otherfile
-
- msgline = START + DEPTH + 1
- @START,0 clear to msgline-2,79
- @START,0 say "Working...."
- do BLINKY
-
- set heading off
- load curson
- load cursoff
- call cursoff
- * DEMO.PRG checked to make sure these existed; your calling program should too
-
- use line
- if field(1) <> "LINE"
- @START,0 say "Please use LINE.DBF that comes with PAGES"
- do BYE_BYE with ""
- return
- endif
- length = iif(len(line) < 78, len(line), 78)
- set safety off
- zap
- set safety on
- append from &FILENAME sdf
- go bottom
- del_num = 0
- do while len(trim(line)) < 1 .and. recno() > 1
- delete
- del_num = del_num + 1
- skip -1
- enddo
- * don't pack
- * wish I could use APPEND FROM &FILENAME FOR LEN(TRIM(LINE)) > 0 SDF,
- * because of interesting way FOR condition works during APPEND,
- * but that would kill blank lines in middle of file; not just at tail-end
-
- tot = reccount() - del_num
-
- if tot < 1
- do WAIT_MSG with "File is empty"
- do BYE_BYE with ""
- return
- endif
-
- page = 1
- size = tot + 1 - MYTOP
- p = size / DEPTH
- q = int(p)
- pages = iif(p - q = 0, q, q + 1)
- end = iif(size < DEPTH, 1, size - DEPTH + START)
- didsearch = .F.
- foundit = 0
- overlap = 0 && this can be changed to anything < DEPTH
-
- if SHOWRULE > 0
- @SHOWRULE,0 to SHOWRULE,78 double
- endif
- @msgline-1,0 to msgline-1,78 double
-
- prompt = iif(pages = 1, "", "Prev, Next, Begin, End, Search, Repeat, #, ") + ;
- iif(SWITCH_OK, "File, ", "") + "or Quit? "
-
- FILENAME = ""
- thisfile = ""
- * FILENAME is pages2's copy of PUBLIC thisfile, declared in calling program
- * demo2.prg and passed to pages2 as parameter. Looks like we have to
- * change BOTH because passed as parameter???
- * extract from LIST MEMORY:
- * THISFILE pub (hidden) C ""
- * FILENAME priv @ THISFILE
- * THISFILE priv C ""
-
- ***************************** main loop ***********************************
- goto MYTOP
- do while .not. eof()
- thispage = "Page " + str(page,2) + " of " + str(pages,2)
- do SHOW_REV with thispage, SHOWPAGE, 66
- if recno() <> MYTOP
- skip overlap + 1
- endif
-
- if .not. deleted()
- @START,0 clear to msgline-2,79
- @START-1,79 && see Liskin, Adv dBase III, p.286, for why
- list off trim(substr(line,1,length)) next DEPTH while .not. deleted()
- endif
- ** all the work is done here
- ** nonprocedural list is 20% faster than procedural do-while loop
- ** and there is another 20% improvement when you trim line
- ** if you wanted to show line numbers, you could:
- ** list trim(substr(line,1,70)) next DEPTH while .not. deleted()
-
- if foundit > 0
- saverec = min(recno(), tot - 1)
- goto foundit
- set color to N/W+
- @START,1 say trim(line) && why trouble if first few lines?
- set color to
- goto saverec
- foundit = 0
- endif
-
- do MSG with prompt
- ink = 0
- do while ink = 0
- ink = inkey()
- enddo
- which = upper(chr(ink))
- num = val(which)
-
- beforerec = recno()
-
- if pages = 1
- do case
- case which = 'F' .and. SWITCH_OK
- do NEW_FILE
- if len(trim(thisfile)) > 0
- return
- endif
- case which = 'Q'
- do BYE_BYE with ""
- return
- otherwise
- do WAIT_MSG with "Only one page"
- do GO_HOME
- endcase
- else
- do case
- case which = 'B' .or. ink = homekey
- do GO_HOME
- case which = 'E' .or. ink = endkey
- do GO_END
- case which = 'P' .or. ink = up .or. ink = pgUp
- do GO_PREV
- case which = 'N' .or. ink = down .or. ink = pgDn
- do GO_NEXT
- case num > 0 && it's a page number
- do GO_PAGE with num
- case which = '#' && if can't get to page with 1 digit
- do ACCEPTVAR with "Go to page #", whichpage
- mypage = val(whichpage)
- do GO_PAGE with mypage
- case which $ "SR"
- do SEARCH
- case which = 'F' .and. SWITCH_OK
- do NEW_FILE
- if len(trim(thisfile)) > 0
- return
- endif
- case which = 'Q'
- do BYE_BYE with ""
- return
- otherwise
- do GO_NEXT
- endcase
- endif
- enddo
- return
-
- *************************** procedures ******************************
- procedure ACCEPTVAR
- parameters msg, var
- @msgline,0
- @msgline,len(msg)
- do BLINKY
- @msgline-1,79
- accept msg to temp
- var = temp
- * var has to be declared PUBLIC
- return
-
- procedure BLINKY && our own blinking cursor: don't call curson
- set color to w*
- ?? '_'
- set color to
- return
-
- procedure BYE_BYE
- parameter sendmessag
- close databases
- call curson
- FILENAME = sendmessag && send message back to caller
- thisfile = sendmessag
- @msgline,0
- return
-
- procedure GO_END
- goto end
- page = pages
- return
-
- procedure GO_HOME
- goto MYTOP
- page = 1
- return
-
- procedure GO_NEXT
- goto iif(eof(), recno() - DEPTH + 1, recno())
- page = iif(page < pages - 1, page + 1, pages)
- return
-
- procedure GO_PAGE
- parameter pg
- pg = iif(pg <= 1, 1, int(pg))
- goto iif(pg >= pages, end, ((pg - 1) * DEPTH) + MYTOP - iif(pg = 1, 0, 1))
- page = iif(pg >= pages, pages, pg)
- return
-
- procedure GO_PREV
- prev = iif(recno() > (DEPTH*2+1), recno()-(DEPTH*2), MYTOP)
- goto prev
- page = iif(page > 1, page - 1, 1)
- return
-
- procedure MSG
- parameter msg
- @msgline,0 clear
- @msgline,0 say msg
- do BLINKY
- return
-
- procedure NEW_FILE
- saverec = iif(recno() - DEPTH > 1, recno() - DEPTH, 1)
- do ACCEPTVAR with "New filename to switch to? ", otherfile
- if file(otherfile)
- do MSG with "Switching file..."
- do BYE_BYE with otherfile
- return
- * depends on calling program PUBLIC variable thisfile
- * this way, pages sends message to calling program rather
- * than recursively calling itself as in previous version of PAGES
- else
- do WAIT_MSG with "No such file"
- goto saverec
- endif
- return
-
- procedure SEARCH
- if which = 'S'
- do ACCEPTVAR with "Search for ", phrase
- endif
- if which = 'S' .or. (which = 'R' .and. didsearch)
- do MSG with "Searching for " + phrase + "..."
- endif
- saverec = iif(recno() - DEPTH > 1, recno() - DEPTH, 1)
- if .not. eof()
- goto saverec + 1
- endif
- if which = 'S'
- locate for at(phrase, line) > 0
- didsearch = .T.
- else if which = 'R'
- if didsearch
- continue
- else
- do WAIT_MSG with "Must do SEARCH before REPEAT"
- endif
- endif
- **** replaced do-while loop with locate/continue
- if .not. found()
- if didsearch
- do WAIT_MSG with "Not found"
- endif
- goto saverec
- else
- foundit = recno()
- skip -1 && back up so they can see it
- page = int(((recno() - MYTOP) / DEPTH) + 1)
- endif
- return
-
- procedure SHOW_REV
- parameters msg, row, col
- @row,col
- @row,col get msg
- clear gets
- return
-
- procedure WAIT_MSG
- parameter msg
- @msgline,len(msg)+32
- do BLINKY
- @msgline-1,79
- wait msg + " ... Press any key to continue "
- @msgline,0
- return
-
- ** missing: need procedure INVAL_SCR to see if screen really needs to
- ** be redrawn. Right now, redraws each time through main loop, even if
- ** nothing has changed.
-
- ** if you're examining source code from within PAGES, please remember to
- ** return to file called PAGES.DAT